PROGRAMMING WITH PRTSTR.DLL (5/15/93) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Introduction: ~~~~~~~~~~~~~ Paradox for Windows (PfW) ObjectPAL (OPAL) simply doesn't allow you to "take control" of your default Windows printer to output text strings directly to it, such as the DOS version of Paradox does. Therefore, the following code is not valid: prtPrint("Hello Printer!", 1) ...until now that is! VS Toolbox Software has now filled this gap in OPAL functionality with our new PrintString Windows DLL (PrtStr), designed expressly to meet the needs of Paradox for Windows application developers just like you. If you were using PrtStr, the code snippet above would print "Hello Printer!" directly to your default Windows printer without your having to create a pre-defined PfW "Report"! PrtStr Function Overview: ~~~~~~~~~~~~~~~~~~~~~~~~~ This Shareware version of PrtStr allows a single instance of your Paradox for Windows application to call any of the following 8 functions: PrtOpen()................... Begins a new printjob PrtLines().................. Returns printer's # of lines per page PrtChars().................. Returns printer's # of chars per line PrtCurrLine()............... Returns the current line # on the page PrtPrint(String, SmallInt).. Prints String + SmallInt # of LineFeeds PrtLF(SmallInt)............. Prints SmallInt # of blank lines PrtFF()..................... Formfeed (starts a new page) PrtClose().................. Ends the current printjob Paradox for Windows "Uses" Clause: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The use of any DLL from within PfW, such as PRTSTR.DLL, requires that you create a "Uses" clause for the specific DLL and it's functions you want to make use of (call). The PfW Form PRTSTR.FSL, included in this Shareware distribution package, provides you with an example of this required code, attached to a single button. Where you locate your PrtStr Uses clause and associated calling code (Library, Script or Form) will depend on the "scope" you want PrtStr to have in your PfW application. (Please refer to pages 45-53 of the OPAL Reference manual for more information about the Uses clause and pages 78-82 of the OPAL Developer's Guide for a discussion about Scope.) The Uses clause necessary for the Shareware version of PrtStr is: uses PRTSTR PrtOpen() CWORD PrtLines() CWORD PrtChars() CWORD PrtCurrLine() CWORD PrtPrint(stringVar CPTR, siVar CWORD) CWORD PrtLF(siVar CWORD) CWORD PrtFF() CWORD PrtClose() CWORD endUses NOTE: stringVar is declared as a String and siVar is declared as a SmallInt. PrtOpen(): ~~~~~~~~~~ The PrtOpen function must be called to BEGIN each new printjob prior to calling any other PrtStr function. PrtOpen does not take any parameters and returns a SmallInt value (we call it a Return Code). PrtOpen performs the following tasks: * Determines if the printer is already 'open'. * Obtains the current default Window's printer driver information. * Resets the PrtStr internal 'lines printed' counter to 0. * Initiates the Windows Print Manager program (if the printer is defined to use the 'Print Spooler'). * Initiates a Windows Print Manager job. * Begins a new Windows 'print' document. * If any step fails, returns a negative return code, else it returns 0. Syntax example: Print the words "Hello Printer!" to the printer... if PrtOpen() = 0 then PrtPrint("Hello Printer!", 1) PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtLines(): ~~~~~~~~~~~ The PrtLines function provides your application with the number of lines per page allowed by the current printer & page orientation. This gives you an opportunity to code your own page-overflow code, if needed. PrtLines does not take any parameters and returns a SmallInt value. NOTE: PrtPrint automatically generates a formfeed if it determines that the next line to be printed would be off the bottom of the page. Syntax example: Print a page footer at the bottom of every page... var linesPerPage, currLineNo, loopCounter SmallInt textVar String endVar if PrtOpen() = 0 then ;open printer linesPerPage = PrtLines() ;set lines per page for loopCounter from 1 to 100 ;begin a loop of 100 if PrtCurrLine() > (linesPerPage - 3) then ;page overflow? PrtLF(1) ;1 linefeed PrtPrint("Page Footer", 1) ;print page footer PrtFF() ;formfeed endIf textVar = "Line # " + strVal(loopCounter) ;build a String PrtPrint(textVar, 1) ;print a line endFor ;end of loop PrtClose() ;close printer else msgInfo("PrtStr Error", "Printer Open failed") endif Character Widths & Line Counts: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following chart is provided for your convenience, as PrtLines and PrtChars provide printer and page orientation specific values to your program. The printer font used by the Shareware version of PrtStr is the default Windows 'system' font. This is a fixed-point (non-proportional) font, which then makes it easy for you to line up columns in your printout. If you use a printer other than one of those listed here, run the PRTSTR.FSL demo form and it will produce a report that shows you the values for your specific printer. Printer Orientation Chars Wide Lines Long ~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ HP LJII Portrait 90 63 HP LJII Landscape 115 48 Postscript Portrait 105 76 Postscript Landscape 139 57 PrtChars(): ~~~~~~~~~~~ The PrtChars function provides your application with the number of characters per line allowed by the current printer & page orientation. This gives you an opportunity to code a string-length-check so PrtStr won't automatically truncate your text string if it's too long. PrtChars does not take any parameters and returns a SmallInt value. NOTE: PrtPrint automatically truncates your text value to the maximum allowable line length specified by the printer and page orientation. Syntax example: Print the number of characters per line allowed... var textVar String endVar if PrtOpen() = 0 then textVar = "Characters per line = " + strVal(PrtChars()) PrtPrint(textVal, 1) PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtCurrLine(): ~~~~~~~~~~~~~~ The PrtCurrLine function provides your application with the current line number of the page being printed. Like PrtLines, this function gives you an opportunity to code your own page-overflow code, if needed. PrtCurrLine does not take any parameters and returns a SmallInt value. Syntax example: Print the current line number on the printout. (For a more complex example, refer to PrtLines.) var textVar String endVar if PrtOpen() = 0 then textVar = "Current print line = " + strVal(PrtCurrLine()) PrtPrint(textVal, 1) PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtPrint(String, SmallInt): ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The PrtPrint function is the whole reason for the PrintString Windows DLL! This function is used to print any PfW/OPAL "string" that you can create. If you need to print any type of numerical value, you must first use OPAL's strVal() function to convert it to a string. You may also use OPAL's format() function to build a pre-formatted string of text and numbers. Parameters to pass: String is a variable you declare as a String, or a literal text string, which contains the actual text you want to have printed. SmallInit is a variable you declare as a SmallInt, which contains the number of linefeeds to be performed after printing the text contained in textVar. A value of 1 tells PrtPrint to add a carriage return/linefeed combination to your text. If you want one or more blank lines printed after your text, then set the value of lines at 2 or greater. PrtPrint performs the following tasks, returning a SmallInt value: * Checks to make sure the printer is 'open'. * Checks to make sure the 'textVar' string passed to PrtStr actually contains data. If not, nothing is done. * Checks to make sure the 'lines' integer passed to PrtStr is greater than 0. If not, it is automatically set to 1. * Checks the length of the string to be printed. If it's longer than allowed by the current printer and page orientation, it is truncated to the maximum line length allowed. * Checks the current line number. If it's greater than the allowable number of lines per page for the current printer and page orientation, an automatic call to PrtFF is performed which generates a Formfeed and resets the current line number to 1. * If all checks are successful: * The contents of the textVal string are printed. * An automatic call to PrtLF is performed the number of times specified via the value in 'SmallInt' (default = 1). * A code of 0 is returned to your program. * If any errors are encountered, a negative return code is returned. Syntax example: Print text in two different ways... var textVar String endVar if PrtOpen() = 0 then textVar = "Hello printer, this is example text #1" ;pre-defined PrtPrint(textVal, 2) PrtPrint("Hello printer, this is example text #2", 1) ;literal PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtLF(SmallInt): ~~~~~~~~~~~~~~~~ The PrtLF function generates a printer LineFeed which prints a blank line the number of times specified via the SmallInt variable. This function is automatically called when PrtPrint() is executed so you don't need to call it in your code unless you want extra blank lines printed under specific circumstances within your program's control. PrtLF takes one parameter, SmallInt, which specifies the number of LineFeeds to be issued, and returns a SmallInt value. Syntax example: If some condition is met, print 3 blank lines... if PrtOpen() = 0 then if someConditionIsMet then ;your own condition goes here PrtLF(3) endIf PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtFF(): ~~~~~~~~ The PrtFF function generates a printer FormFeed. PrtFF is called automatically by PrtPrint() if the page's current line number becomes greater than the allowable number of lines per page. PrtFF does not take any parameters, returns a SmallInt value and performs the following tasks: * Issues a FormFeed command to the printer. If a Formfeed could not be generated due to low memory or low disk drive space (unable to continue spooling the printjob): * An automatic call to PrtClose is performed, which cancels the printjob and resets the printer status to 'Closed'. * A Windows message box is displayed to the user (in case they can correct the low memory or disk space condition). * A negative return code is sent back to your program. * Resets the current line number to 1. * If all went well, a code of 0 is returned to your program. Syntax example: If some condition is met, start a new page... if PrtOpen() = 0 then if someConditionIsMet then ;your own condition goes here PrtFF() endIf PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endif PrtClose(): ~~~~~~~~~~~ The PrtClose function must be called to END each printjob started with PrtOpen. If it's not called, your report will not be sent from the print spooler to the physical printer. PrtClose does not take any parameters and returns a SmallInt value. PrtClose performs the following tasks: * Ends the current Windows print document. * Ejects the last page of the print document (calls PrtFF). * Terminates the Windows Print Manager job which releases it to print. * If it was the last print job, Windows closes the Print Manager. * Resets the internal Printer 'Open' status to 'Closed'. * Resets the current line number to 1. * If any step fails, returns a negative return code, else it returns 0. Syntax example: Close the printer... If PrtOpen() = 0 then PrtPrint("Goodbye printer...", 1) PrtClose() else msgInfo("PrtStr Error", "Printer Open failed") endIf PrtStr 'Return Codes': ~~~~~~~~~~~~~~~~~~~~~~ Each of the PrtStr functions returns a SmallInt value (CWORD), which is referred to as the "return code", to let you know of it's success or failure. The return codes are: 0 = Successful - no further action required. -1 = Printer already open - printjob currently in progress. -2 = Unable to process a FormFeed request. Printer is now 'Closed'. -3 = Unable to 'Open' a new printjob. Printer is now 'Closed'. -4 = Unable to 'Start' a new printjob. Printer is now 'Closed'. -5 = Printer is not currently 'Open'. *-6 = Low disk space encountered by spooler. Printer is now 'Closed'. *-7 = Low memory encountered by spooler. Printer is now 'Closed'. * This error will result in a Windows MessageBox being displayed to the user, since it may be the result of low memory or low disk space, which you might not be able to plan for in your application, but the user might be able to fix and re-run the requested job. Using PrtStr Return Codes: ~~~~~~~~~~~~~~~~~~~~~~~~~~ A typical printout to be generated by PrtStr function calls from within a pushButton method might look something like the example on the following pages. (NOTE: A more complete example is provided 'live' in the un-delivered PRTSTR.FSL form included in this Shareware distribution package.) It is suggested that you use this return-code checking method of calling PrtStr functions to begin each new report. Once you are certain that the results are what you expect, you can start replacing code. The one return code check which should ALWAYS be performed is PrtOpen. If PrtStr cannot open the printer, all subsequent function calls will fail. Syntax Example: pushButton method to print "Hello Printer!" and display PrtStr errors if any are encountered... ;Define variables global to this method... var errMsg String rtnCode SmallInt endvar ;Define the error-handling, on-screen display proc... proc PrtStrError() switch case rtnCode = -1 : errMsg = "Printer already 'Open'." case rtnCode = -2 : errMsg = "Unable to process a FormFeed.\n" + "Printer is Closed." case rtnCode = -3 : errMsg = "Unable to 'Open' a new printjob.\n" + "Printer is Closed." case rtnCode = -4 : errMsg = "Unable to 'Start' a new printjob.\n" + "Printer is Closed." case rtnCode = -5 : errMsg = "Printer is not 'Open'." case rtnCode = -6 : errMsg = "Print spooler reported low disk space.\n" + "Printjob cancelled. Printer is Closed." case rtnCode = -7 : errMsg = "Print spooler reported low memory.\n" + "Printjob cancelled. Printer is Closed." otherwise : errMsg = "Unknown error returned from PrtStr." endswitch msgInfo("PrtStr DLL Error", errMsg) endProc ;(Start of the actual pushButton method code...) method pushButton(var eventInfo Event) ;Open the printer... rtnCode = PrtOpen() ; this gives you a 'return code' you can validate ;Check for errors... if rtnCode < 0 then PrtStrError() return endif ;Print a line of text...<> rtnCode = PrtPrint("Hello Printer!", 1) if rtnCode < 0 then PrtStrError() return endif ;Close the printer rtnCode = PrtClose() if rtnCode < 0 then PrtStrError() return else msgInfo("Message from PrtStr DLL", "Printjob now completed.") endif endmethod